[HVM][SVM] This patch cleans up the SVM CPUID logic a bit, adds proper clearing
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 19 Sep 2006 10:03:12 +0000 (11:03 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 19 Sep 2006 10:03:12 +0000 (11:03 +0100)
of MCA/MCE bits, and also ties clearing the PAE bit with the NX bit. We
have seen issues with Solaris if the NX bit is set but the PAE bit is
not.

Signed-off-by: Tom Woller <thomas.woller@amd.com>=20
xen/arch/x86/hvm/svm/svm.c

index 59ccbb1dd0e6114a8461c7e4fccd4e8af09625b1..1b26ebc13f0710c374e7c0ee1dc87c7b32a2c401 100644 (file)
@@ -1041,95 +1041,76 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
                 (unsigned long)regs->ecx, (unsigned long)regs->edx,
                 (unsigned long)regs->esi, (unsigned long)regs->edi);
 
-    cpuid(input, &eax, &ebx, &ecx, &edx);
-
-    if (input == 0x00000001)
+    if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
     {
-        if ( !hvm_apic_support(v->domain) ||
-             !vlapic_global_enabled((VLAPIC(v))) )
+        cpuid(input, &eax, &ebx, &ecx, &edx);       
+        if (input == 0x00000001 || input == 0x80000001 )
         {
-            /* Since the apic is disabled, avoid any confusion 
-               about SMP cpus being available */
-            clear_bit(X86_FEATURE_APIC, &edx);
-        }
-
+            if ( !hvm_apic_support(v->domain) ||
+                 !vlapic_global_enabled((VLAPIC(v))) )
+            {
+                /* Since the apic is disabled, avoid any confusion 
+                   about SMP cpus being available */
+                clear_bit(X86_FEATURE_APIC, &edx);
+            }
 #if CONFIG_PAGING_LEVELS >= 3
-        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
+            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
 #endif
-            clear_bit(X86_FEATURE_PAE, &edx);
-        clear_bit(X86_FEATURE_PSE36, &edx);
-
-        /* Clear out reserved bits. */
-        ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
-        edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
+            {
+                clear_bit(X86_FEATURE_PAE, &edx);
+                if (input == 0x80000001 )
+                   clear_bit(X86_FEATURE_NX & 31, &edx);
+            }
+            clear_bit(X86_FEATURE_PSE36, &edx);
+            /* Disable machine check architecture */
+            clear_bit(X86_FEATURE_MCA, &edx);
+            clear_bit(X86_FEATURE_MCE, &edx);
+            if (input == 0x00000001 )
+            {
+                /* Clear out reserved bits. */
+                ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
+                edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
 
-        clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
+                clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
 
-        /* Guest should only see one logical processor.
-         * See details on page 23 of AMD CPUID Specification. 
-         */
-        clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
-        ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
-        ebx |= 0x00010000;  /* set to 1 just for precaution */
+                /* Guest should only see one logical processor.
+                 * See details on page 23 of AMD CPUID Specification. 
+                 */
+                clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
+                ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
+                ebx |= 0x00010000;  /* set to 1 just for precaution */
+            }
+            else
+            {
+                /* Clear the Cmp_Legacy bit 
+                 * This bit is supposed to be zero when HTT = 0.
+                 * See details on page 23 of AMD CPUID Specification. 
+                 */
+                clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
+                /* Make SVM feature invisible to the guest. */
+                clear_bit(X86_FEATURE_SVME & 31, &ecx);
+#ifdef __i386__
+                /* Mask feature for Intel ia32e or AMD long mode. */
+                clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
 
-        /* Disable machine check architecture */
-        clear_bit(X86_FEATURE_MCA, &edx);
-        clear_bit(X86_FEATURE_MCE, &edx);
-    }
-    else if ( (input > 0x00000005) && (input < 0x80000000) )
-    {
-        if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
+                clear_bit(X86_FEATURE_LM & 31, &edx);
+                clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
+#endif
+                /* So far, we do not support 3DNow for the guest. */
+                clear_bit(X86_FEATURE_3DNOW & 31, &edx);
+                clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
+            }
+        }
+        else if ( ( input == 0x80000007 ) || ( input == 0x8000000A  ) )
+        {
+            /* Mask out features of power management and SVM extension. */
             eax = ebx = ecx = edx = 0;
-    }
-    else if ( input == 0x80000001 )
-    {
-        /* We duplicate some CPUID_00000001 code because many bits of 
-           CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
-
-        if ( !hvm_apic_support(v->domain) ||
-             !vlapic_global_enabled((VLAPIC(v))) )
+        }
+        else if ( input == 0x80000008 )
         {
-            /* Since the apic is disabled, avoid any confusion 
-               about SMP cpus being available */
-            clear_bit(X86_FEATURE_APIC, &edx);
+            /* Make sure Number of CPU core is 1 when HTT=0 */
+            ecx &= 0xFFFFFF00; 
         }
-
-        /* Clear the Cmp_Legacy bit 
-         * This bit is supposed to be zero when HTT = 0.
-         * See details on page 23 of AMD CPUID Specification. 
-         */
-        clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
-
-#ifdef __i386__
-        /* Mask feature for Intel ia32e or AMD long mode. */
-        clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
-
-        clear_bit(X86_FEATURE_LM & 31, &edx);
-        clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
-#endif
-
-
-#if CONFIG_PAGING_LEVELS >= 3
-        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
-#endif
-            clear_bit(X86_FEATURE_PAE, &edx);
-        clear_bit(X86_FEATURE_PSE36, &edx);
-
-        /* Make SVM feature invisible to the guest. */
-        clear_bit(X86_FEATURE_SVME & 31, &ecx);
-
-        /* So far, we do not support 3DNow for the guest. */
-        clear_bit(X86_FEATURE_3DNOW & 31, &edx);
-        clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
-    }
-    else if ( ( input == 0x80000007 ) || ( input == 0x8000000A  ) )
-    {
-        /* Mask out features of power management and SVM extension. */
-        eax = ebx = ecx = edx = 0;
-    }
-    else if ( input == 0x80000008 )
-    {
-        ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
     }
 
     regs->eax = (unsigned long)eax;